package im.composer.vapu.adapter;

import im.composer.media.sound.synth.SoftSynthesizer;
import im.composer.midi.remote.RawMidiMessage;
import im.composer.vapu.VAPU;

import java.util.Collections;
import java.util.List;

import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Transmitter;
import javax.sound.sampled.AudioFormat;

import org.jaudiolibs.audioservers.AudioConfiguration;
import org.tritonus.share.sampled.FloatSampleInput;

import themidibus.listener.RawMidiListener;

public class GervillSynth extends VAPU implements RawMidiListener {

	private transient SoftSynthesizer synth;
	private transient FloatSampleInput fsi;

	public GervillSynth() {
		super();
	}

	public GervillSynth(AudioConfiguration context){
		super(context);
	}

	@Override
	public synchronized void configure(AudioConfiguration context) throws Exception {
		super.configure(context);
		if(synth==null){
			synth = new SoftSynthesizer();
		}
		AudioFormat format = new AudioFormat(context.getSampleRate(), 32, context.getOutputChannelCount(), true, false);
		fsi = synth.openFloatInput(format, Collections.<String, Object> emptyMap());
	}

	public Synthesizer getSynthesizer() {
		return synth;
	}

	@Override
	public void close() {
		synth.close();
	}

	@Override
	protected void computeBuffer() {
		fsi.read(buf);
	}

	@Override
	public void rawMidiMessage(byte[] data) {
		try {
			synth.getReceiver().send(new RawMidiMessage(data), synth.getMicrosecondPosition());
		} catch (MidiUnavailableException e) {
		}
	}
//
//	@Override
//	public void send(MidiMessage message, long timeStamp) {
//		try {
//			synth.getReceiver().send(message, timeStamp);
//		} catch (MidiUnavailableException e) {
//		}
//	}

	public boolean isOpen() {
		return synth.isOpen();
	}

	public long getMicrosecondPosition() {
		return synth.getMicrosecondPosition();
	}

	public int getMaxReceivers() {
		return synth.getMaxReceivers();
	}

	public int getMaxTransmitters() {
		return synth.getMaxTransmitters();
	}

	public Receiver getReceiver() {
		try {
			return synth.getReceiver();
		} catch (MidiUnavailableException e) {
			return this;
		}
	}

	public List<Receiver> getReceivers() {
		return synth.getReceivers();
	}

	public Transmitter getTransmitter() throws MidiUnavailableException {
		return synth.getTransmitter();
	}

	public List<Transmitter> getTransmitters() {
		return synth.getTransmitters();
	}

	@Override
	public void executeCommand(long timeStamp, String command) {
		
	}

}
